home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 21
/
AACD 21.iso
/
AACD
/
Resources
/
Online
/
Miami
/
MiamiSDK
/
examples
/
ttcptest.c
< prev
Wrap
C/C++ Source or Header
|
1997-12-28
|
5KB
|
223 lines
/*
* ttcptest.c
*
* Small example for a T/TCP-compliant client.
*
* This client tries to connect to the auth (identd) port of the
* specified host using T/TCP. If T/TCP is not supported it falls
* back to TCP.
*
* (C) Copyright 1996,1997 by Nordic Global Inc. All rights reserved.
* T/TCP code for use with Miami only.
*
* 07/30/97: first version
*
* 12/28/97: - added support for PPC
* - added support for protocol-independent hostname lookup
* (for IPv6 compatibility)
*/
#define __USE_SYSBASE
#include <proto/exec.h>
#include <proto/miami.h>
#include <proto/socket.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <dos.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
struct Library *MiamiBase=0;
static int dottcp=0;
static int protoind=0;
#define REQUEST "1 : 1\r\n"
void myexit(void) {
if(MiamiBase) {
CloseLibrary(MiamiBase);
MiamiBase=0;
}
}
int mybreak(void) {
myexit();
return 1;
}
void get_response(int sockfd,char *buf,int max) {
int len=0,le;
while(len<max-1) {
le=recv(sockfd,buf+len,max-len-1,0);
if(le==0) {
buf[len]=0;
return;
}
if(le<0) {
fprintf(stderr,"recv: error %d\n",Errno());
exit(10);
}
len+=le;
}
buf[max-1]=0;
}
void main(int argc,char **argv) {
struct hostent *he;
struct servent *se;
long sockfd,n=1,err,family,sockettype;
char buf[256];
struct sockaddr_in sin;
struct sockaddr *sa;
struct addrinfo *addrinfo=0;
if(argc==0)
exit(0);
if(argc!=2) {
fprintf(stderr,"Usage: %s host\n",argv[0]);
exit(10);
}
/* install exit and break hooks so MiamiBase gets closed
in all cases */
atexit(myexit);
#ifndef __PPC__
/* onbreak() is not supported by SAS/C-PPC yet */
onbreak(mybreak);
#endif
/* miami.library versions >= 3 support T/TCP */
if(MiamiBase=OpenLibrary("miami.library",3)) {
dottcp=1;
/* miami.library versions >= 12 support protocol-
independent hostname lookup (IPv6 compatible) */
if(MiamiBase->lib_Version>=12)
protoind=1;
}
/* ---- host name / service stuff */
if(protoind) {
/* new protocol-independent version */
if(getaddrinfo(argv[1],"auth",0,&addrinfo)) {
fprintf(stderr,"Host `%s' with service `auth' not found\n",argv[1]);
exit(10);
}
family=addrinfo->ai_family;
sockettype=addrinfo->ai_socktype;
sa=addrinfo->ai_addr;
} else {
/* old IPv4-only version */
if(!(he=gethostbyname(argv[1]))) {
fprintf(stderr,"Host `%s' not found\n",argv[1]);
exit(10);
}
if(!(se=getservbyname("auth","tcp"))) {
fprintf(stderr,"Service `auth' not found\n");
exit(10);
}
sin.sin_family=family=AF_INET;
sockettype=SOCK_STREAM;
sin.sin_len=sizeof(sin);
memcpy(&sin.sin_addr,he->h_addr,he->h_length);
sin.sin_port=se->s_port;
sa=(struct sockaddr *)&sin;
}
if(0>(sockfd=socket(family,sockettype,0))) {
fprintf(stderr,"Unable to create socket\n");
exit(10);
}
/* ---- start of T/TCP stuff */
if(dottcp) {
/* The following call is useful if a sendto() may be larger than
the MSS, to ensure that packets are packed tightly. (If this seems
strange, that's probably because it is. It has to do with some
odd quirks in the implementation of sosend() in all BSD-derived
TCP/IP stacks. Don't ask any questions -- just add this call
to your program :-)).
HOWEVER: only add the call if you do NOT reuse your TCP connection
for multiple requests. If you want to transmit multiple pairs of
"transaction"/"response" across the same TCP link (e.g. HTTP 1.1
"persistent TCP connections"), then do NOT add the following
call. */
setsockopt(sockfd,IPPROTO_TCP,TCP_NOPUSH,(char *)&n,sizeof(n));
/* Instead of the usual connect() followed by send(), for T/TCP you
use a sendto() call, as you would for UDP sockets.
If you have a known amount of data to send that you can send in
a single function call, then you should use one single sendto()
call with the MSG_EOF flag set, as in this example. This is the
preferred way to do it, and gives best performance.
If you absolutely need to loop then use a sequence like
sendto(,,,0,,);
while(!done) {
send(,,,0);
}
send(,,,MSG_EOF);
this means set the MSG_EOF flag in the *last* send() call only.
MSG_EOF performs an implicit shutdown() for one direction of the
link, improving performance because the shutdown() can be
piggy-backed on data packets, i.e. no additional packets are
needed for a shutdown() or CloseSocket() later.
However *do not* use MSG_EOF if you want to re-use your
connection for subsequent requests (e.g. "persistent TCP
connections" in HTTP-1.1). */
if(sendto(sockfd,REQUEST,strlen(REQUEST),MSG_EOF,sa,sa->sa_len)
!=strlen(REQUEST)) {
if((err=Errno())==ENOTCONN) {
/* T/TCP failed. Try ordinary TCP */
dottcp=0;
} else {
fprintf(stderr,"sendto: error %d\n",err);
exit(10);
}
}
}
/* ---- end of T/TCP stuff */
if(!dottcp) {
if(connect(sockfd,sa,sa->sa_len)<0) {
fprintf(stderr,"connect: error %d\n",Errno());
exit(10);
}
if(send(sockfd,REQUEST,strlen(REQUEST),0)!=strlen(REQUEST)) {
fprintf(stderr,"send: error %d\n",Errno());
exit(10);
}
}
get_response(sockfd,buf,256);
puts(buf);
CloseSocket(sockfd);
if(addrinfo)
freeaddrinfo(addrinfo);
}